package cn.itcast.nems.studentrecord.service.impl;

import cn.itcast.ic.common.exception.v2.BizExceptionProducer;
import cn.itcast.ic.common.exception.v2.bean.BizStatusEnum;
import cn.itcast.nems.base.api.BusinessLineApi;
import cn.itcast.nems.base.api.OriginChannelApi;
import cn.itcast.nems.base.api.PaymentTypeApi;
import cn.itcast.nems.base.dao.mapper.PreStudentInfoMapper;
import cn.itcast.nems.base.dto.BusinessLineDTO;
import cn.itcast.nems.base.dto.OriginChannelDTO;
import cn.itcast.nems.base.dto.PaymentTypeDTO;
import cn.itcast.nems.common.account.AccountHolder;
import cn.itcast.nems.common.account.AccountInfo;
import cn.itcast.nems.discount.api.DiscountApi;
import cn.itcast.nems.discount.dto.DiscountSummaryDTO;
import cn.itcast.nems.manager.scrm.SCRMManager;
import cn.itcast.nems.manager.scrm.dto.CustomerInfo;
import cn.itcast.nems.order.api.OrderApi;
import cn.itcast.nems.order.dto.*;
import cn.itcast.nems.product.dao.dataobject.BizNo;
import cn.itcast.nems.studentrecord.constant.OrderSourceEnum;
import cn.itcast.nems.studentrecord.dto.change.StudentRecordChangeDTO;
import cn.itcast.nems.studentrecord.dto.change.StudentRecordChangeDiscountDTO;
import cn.itcast.nems.studentrecord.dto.studentrecord.StudentRecordOrderCreateResultDTO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author liyong
 * create: 2023-11-21 15:56:22
 **/
@AllArgsConstructor
@Service
class OrderApiDelegate {
    private final OrderApi orderApi;
    private final OriginChannelApi originChannelApi;
    private final BusinessLineApi businessLineApi;
    private final PaymentTypeApi paymentTypeApi;
    private final DiscountApi discountApi;
    private final PreStudentInfoMapper preStudentInfoMapper;
    private final SCRMManager scrmManager;

    OrderApi getOrderApi() {
        return this.orderApi;
    }

    /**
     * 增加订单流水
     *
     * @param flowDTO 参数对象
     */
    void addPaymentFlow(PaymentFlowDTO flowDTO) {
        this.orderApi.addPaymentFlow(flowDTO);
    }

    /**
     * 查询订单
     *
     * @param bizOrderNo 业务订单号
     * @return 订单，不存在返回null
     */
    OrderMode findByBizOrderNo(String bizOrderNo) {
        return this.orderApi.findByBizOrderNo(bizOrderNo);
    }

    /**
     * 取消订单
     *
     * @param orderId 订单ID
     */
    void cancel(String orderId) {
        this.orderApi.cancel(orderId);
    }

    /**
     * 根据订单ID获取订单详情
     *
     * @param orderId 订单ID
     * @return 订单信息
     */
    OrderMode findById(String orderId) {
        return this.orderApi.findById(orderId);
    }

    /**
     * 创建订单
     *
     * @param studentRecordChange 学籍变更参数
     * @param orderSource         订单来源
     * @param bizOrderNo          业务订单号
     * @return 新创建的订单ID
     */
    StudentRecordOrderCreateResultDTO createOrder(StudentRecordChangeDTO studentRecordChange,
                                                  OrderSourceEnum orderSource,
                                                  String bizOrderNo) {
        NewOrderDTO order = new NewOrderDTO();
        order.setSource(orderSource.toString());
        order.setBizOrderNo(bizOrderNo);
        order.setBizDate(LocalDateTime.now());
        String channelCode = "NEMS";
        final List<OriginChannelDTO> channels = this.originChannelApi.findByParam(new OriginChannelDTO(channelCode));
        if (channels == null || channels.isEmpty()) {
            BizExceptionProducer.throwServerError(BizStatusEnum.BAD_REQUEST.toString(), "来源代码'%s'没有找到", channelCode);
        }
        OriginChannelDTO channel = channels.get(0);
        order.setOriginChannelId(channel.getId());
        order.setOriginChannelName(channel.getName());
        String paymentTypeCode = "FIRSTPAYMENT";
        List<PaymentTypeDTO> types = paymentTypeApi.findByParam(new PaymentTypeDTO(null, paymentTypeCode));
        if (types == null || types.isEmpty()) {
            BizExceptionProducer.throwServerError(BizStatusEnum.BAD_REQUEST.toString(), "付款方式代码'%s'没有找到", paymentTypeCode);
        }
        PaymentTypeDTO type = types.get(0);
        order.setPaymentTypeId(type.getId());
        order.setPaymentTypeName(type.getName());
        order.setRemark(orderSource.getCname() + "订单");
        order.setPaidAmount(0);
        String createBy = AccountHolder.getRequiredAccountInfo().getEmail();
        order.setCreatedBy(createBy);
        String businessLineCode = "DUAN_XUN";
        List<BusinessLineDTO> lines = businessLineApi.findByParam(new BusinessLineDTO(businessLineCode));
        if (lines == null || lines.isEmpty()) {
            BizExceptionProducer.throwServerError(BizStatusEnum.BAD_REQUEST.toString(), "业务线代码'%s'没有找到", businessLineCode);
        }
        BusinessLineDTO line = lines.get(0);
        order.setBusinessLineId(line.getId());
        order.setBusinessLineName(line.getName());
        String productBizNo = BizNo.calBizNo(studentRecordChange.getTargetClazzId());
        order.setDiscounts(this.createOrderDiscounts(studentRecordChange, productBizNo));
        order.setLines(this.createOrderLine(order, studentRecordChange, productBizNo));
        order.setOrderCustomerRelationship(this.createOrderCustomerRelationship(studentRecordChange.getStudentId()));
        final CreateOrderResultDTO orderResultDTO = this.orderApi.create(order);
        final StudentRecordOrderCreateResultDTO result = new StudentRecordOrderCreateResultDTO();
        result.setOrderResultDTO(orderResultDTO);
        result.setBizDate(order.getBizDate().toLocalDate());
        result.setAmount(studentRecordChange.getTargetClazzActualAmountDue());
        return result;
    }

    private List<NewOrderLineDTO> createOrderLine(NewOrderDTO order,
                                                  StudentRecordChangeDTO studentRecordChange,
                                                  String productBizNo) {
        NewOrderLineDTO line = new NewOrderLineDTO();
        line.setProductBizNo(productBizNo);
        line.setPrice(studentRecordChange.getTargetClazzPrice());
        line.setQuantity(1);
        line.setOriginalAmount(line.getPrice());
        line.setDiscountAmount(0);
        final List<NewOrderDiscountDTO> discounts = order.getDiscounts();
        if (discounts != null && !discounts.isEmpty()) {
            final int discountAmount = discounts
                    .stream()
                    .mapToInt(NewOrderDiscountDTO::getDiscountAmount)
                    .sum();
            line.setDiscountAmount(discountAmount);
        }
        // int amountDue = line.getOriginalAmount() - line.getDiscountAmount();
        int amountDue = studentRecordChange.getTargetClazzActualAmountDue();
        amountDue = Math.max(amountDue, 0);
        line.setAmountDue(amountDue);
        return List.of(line);
    }

    private List<NewOrderDiscountDTO> createOrderDiscounts(StudentRecordChangeDTO studentRecordChange, String productBizNo) {
        List<NewOrderDiscountDTO> result = new ArrayList<>();
        final List<StudentRecordChangeDiscountDTO> discounts = studentRecordChange.getDiscounts();
        if (discounts != null && !discounts.isEmpty()) {
            final Map<Integer, DiscountSummaryDTO> discountMap = this.findDiscountSummarys(discounts);
            discounts.forEach(d -> {
                NewOrderDiscountDTO dto = new NewOrderDiscountDTO();
                final int discountId = Integer.parseInt(d.getDiscountId());
                dto.setDiscountId(d.getDiscountId());
                dto.setProductBizNo(productBizNo);
                final DiscountSummaryDTO summary = discountMap.get(discountId);
                dto.setDescription(summary.getDescription());
                dto.setDiscountAmount(d.getDiscountAmount());
                dto.setSort(d.getSort());
                result.add(dto);
            });
        }
        return result;
    }

    /**
     * 查询优惠详情
     *
     * @param discounts 优惠
     * @return key: discountId, value: DiscountSummaryDTO
     */
    private Map<Integer, DiscountSummaryDTO> findDiscountSummarys(List<StudentRecordChangeDiscountDTO> discounts) {
        final Set<String> discountIds = discounts
                .stream()
                .map(StudentRecordChangeDiscountDTO::getDiscountId)
                .collect(Collectors.toSet());
        final Set<DiscountSummaryDTO> summarys = this.discountApi.getSummaryByIds(discountIds);
        return summarys
                .stream()
                .collect(Collectors.toMap(DiscountSummaryDTO::getId, Function.identity()));
    }

    private NewOrderCustomerRelationshipDTO createOrderCustomerRelationship(int studentId) {
        final Integer customerId = this.preStudentInfoMapper.selectCustomerId(studentId);
        if(customerId == null){
            BizExceptionProducer.throwBadRequest(BizStatusEnum.BAD_REQUEST.name(), "学员ID: %d 根据报名信息没有找到对应的客户", studentId);
        }
        final CustomerInfo customer = this.scrmManager.findCustomerInfo(customerId);
        NewOrderCustomerRelationshipDTO result = new NewOrderCustomerRelationshipDTO();
        result.setCustomerId(String.valueOf(customerId));
        result.setCustomerName(customer.getName());
        result.setCustomerMobile(customer.getPhone());
        result.setCustomerGender(customer.getGender());
        result.setCustomerQq(customer.getQq());
        result.setCustomerWechat(customer.getWechat());
        result.setCounselorId(String.valueOf(customer.getBelongerId()));
        result.setCounselorName(customer.getBelongerName());
        result.setCounselorEmail(customer.getBelongerEmail());
        result.setCounselorTeam(customer.getBelongerDepartment());
        AccountInfo accountInfo = AccountHolder.getRequiredAccountInfo();
        result.setOperatorEmail(accountInfo.getEmail());
        result.setOperatorName(accountInfo.getName());
        return result;
    }
}
